package scalahighlevel

import scala.reflect.ClassTag

/**
  * scala的泛型
  * @tparam T
  */
class Generic[T] {
  //定义一个变量
  private var content:T = _

  //定义get和set方法
  def set(value:T) = {content = value}
  def get():T = {content}

  def mkArray[T:ClassTag](elems:T*) = Array[T](elems:_*)
}

object GenericClass {

  def main(args: Array[String]): Unit = {
    //操作Int
    //    var intGeneric = new Generic[Int]
    //    intGeneric.set(123)
    //    println("得到的值:" + intGeneric.get())
    //
    //    //操作String
    //    var stringGeneric = new Generic[String]
    //    stringGeneric.set("Hello Scala")
    //    println("得到的值:" + stringGeneric.get())
    /**
      * 泛型函数
      */
    //    创建一个函数，功能：创建一个Int类型的数组
    def mkIntArray(elems:Int*) = Array[Int](elems:_*)
    mkIntArray(1,2,3,4,5)

    //    创建一个函数，功能：创建一个String类型的数组
    def mkStringArray(elems:String*) = Array[String](elems:_*)
    mkStringArray("Tom","Mary","Mike")

    //    问题：能否创建一个通用的函数，既能创建Int类型数组，也能创建String类型的数组
    //    在泛型函数中：T有要求：必须是ClassTag类型
    //    ClassTag: 表示执行Scala程序时的运行信息，该例子中，表示数据的类型


    //和泛型类相结合的函数，要哪种类型得先创建哪种类型的类，所以有时候直接定义函数比较方便
    println(new Generic[Int].mkArray(1,2,3,4,5).foreach(println _))
    println(new Generic[String].mkArray("Tom","Mary","Mike").foreach(println _))
    //比上边使用泛型类方便多了，所以有些时候考虑直接定义函数会更方便
    def mkArray[T:ClassTag](elems:T*) = Array[T](elems:_*)
    mkArray("Tom","Mary","Mike")
    mkArray(1,2,3,4,5)


  }
}